const Controller = require('egg').Controller;
const fs = require('fs');
const path = require('path');

function getFlvHeader(filePath) {
  const headerBuffer = Buffer.alloc(9);
  const fd = fs.openSync(filePath, 'r');
  fs.readSync(fd, headerBuffer, 0, 9, 0);
  fs.closeSync(fd);
  return headerBuffer;
}

function prependHeaderToChunk(headerBuffer, chunkPath) {
  const chunkBuffer = fs.readFileSync(chunkPath);
  const newBuffer = Buffer.concat([headerBuffer, chunkBuffer]);
  fs.writeFileSync(chunkPath, newBuffer);
}

function ensureDirectoryExistence(filePath) {
  const dirname = path.dirname(filePath);
  if (!fs.existsSync(dirname)) {
    fs.mkdirSync(dirname, { recursive: true });
  }
}

class VideoController extends Controller {
  async serveVideo() {
    const { ctx } = this;
    const videoFilePath = path.join(this.config.baseDir, 'app/public/videos/output.flv');
    const fileSize = fs.statSync(videoFilePath).size;
    const headerBuffer = getFlvHeader(videoFilePath);
    console.log('headerBuffer', headerBuffer);
    const range = ctx.request.headers.range;

    if (range) {
      const [start, end] = range.replace(/bytes=/, "").split("-");
      const startPos = parseInt(start, 10);
      const endPos = end ? parseInt(end, 10) : fileSize - 1;
      
      if (startPos >= fileSize) {
        ctx.status = 416;
        ctx.body = { error: 'Requested range not satisfiable' };
        return;
      }

      const chunkSize = (endPos - startPos) + 1;
      const chunkPath = path.join(this.config.baseDir, 'app/public/videos/output_chunk.flv');
      
      ensureDirectoryExistence(chunkPath);
      
      const chunkStream = fs.createReadStream(videoFilePath, { start: startPos, end: endPos });
      const writeStream = fs.createWriteStream(chunkPath);
      
      chunkStream.pipe(writeStream);

      writeStream.on('finish', () => {
        prependHeaderToChunk(headerBuffer, chunkPath);
        const fileStream = fs.createReadStream(chunkPath);

        fs.readFile(chunkPath, (err, data) => {
          if (err) throw err;
          // console.log(data); // 检查文件内容
        });

        // console.log('fileStream', fileStream);
        ctx.set('Content-Range', `bytes ${startPos}-${endPos}/${fileSize}`);
        ctx.set('Accept-Ranges', 'bytes');
        ctx.set('Content-Length', chunkSize);
        ctx.set('Content-Type', 'video/x-flv');
        ctx.status = 206;
        ctx.body = fileStream;
      });

      writeStream.on('error', (err) => {
        ctx.status = 500;
        ctx.body = { error: 'Error writing file' };
      });

    } else {
      ctx.set('Content-Length', fileSize);
      ctx.set('Content-Type', 'video/x-flv');
      ctx.body = fs.createReadStream(videoFilePath);
    }
  }

  async getFlvHeader() {
    const { ctx } = this;
    const filePath = path.join(this.config.baseDir, 'app/public/videos/output.flv');

    if (!fs.existsSync(filePath)) {
      ctx.status = 404;
      ctx.body = { error: 'File not found' };
      return;
    }

    const buffer = fs.readFileSync(filePath);
    const signature = buffer.toString('ascii', 0, 3);
    if (signature !== 'FLV') {
      ctx.status = 400;
      ctx.body = { error: 'Not a valid FLV file' };
      return;
    }

    const version = buffer.readUInt8(3);
    const flags = buffer.readUInt8(4);
    const headerLength = buffer.readUInt32LE(5);

    ctx.body = {
      'FLV Signature': signature,
      'Version': version,
      'Flags': flags,
      'Header Length': headerLength,
    };
  }
}

module.exports = VideoController;
